/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Basketball;

import VISIE.characters.BasketballAgent;
import VISIE.characters.BasketballCharacter;
import VISIE.scenemanager.SceneCharacterManager;
import java.util.ArrayList;
import VISIE.characters.Character;
import VISIE.mathfunctions.CollisionMath;
import VISIE.mathfunctions.Conversions;
import VISIE.scenemanager.Court;
import com.jme3.math.Vector3f;

/**
 *
 * @author Divesh
 */
public class NonPossessionDecision {
    
    BasketballAgent parentCharacter;
    
    public NonPossessionDecision(BasketballAgent ba){
        parentCharacter = ba;
    }
    
    public void findFreeSpace(){
        
        //if player can receive open pass
              
        BasketballCharacter bcInPos = SceneCharacterManager.getCharacterInPossession();       
        String possPos = Court.getPlayerArea(bcInPos);        
        
        ArrayList<ArrayList<String>> areas = AgentPlanning.getPlayerAreas(parentCharacter, bcInPos);
        
        //if open for pass, stand still to face player with ball 
        if(this.openForPass(bcInPos) && parentCharacter.get2DPosition().distance(bcInPos.get2DPosition()) < 15f){
            parentCharacter.planner.setTargetPosition(parentCharacter.getPosition());
        }
        //if not open, calculate best position to travel to 
        else{
            this.calculateBestPosition(bcInPos, possPos, areas.get(0), areas.get(1));
        }
        
    }
    
    private void calculateBestPosition(BasketballCharacter bcInPos, String possession, ArrayList<String> teammates, ArrayList<String> opponents){
        
        //finds candidate areas
        ArrayList<String> candidates = Court.getAdjacentAreas(possession);
        
        ArrayList<String> emptyRegions = new ArrayList<String>();
        String currentArea = Court.getPlayerArea(parentCharacter);
        boolean stayStill = false;
        
        //labels candidate areas if they contain players
        for(int i = candidates.size() - 1; i >= 0; i--){
            for(int j = 0; j < teammates.size(); j++){
                if(candidates.get(i).equals(teammates.get(j))){
                    candidates.set(i, "T: " + candidates.get(i));
                }
            }
            for(int k = 0; k < opponents.size(); k++){
                if(candidates.get(i).equals(opponents.get(k))){
                    candidates.set(i, "O: " + candidates.get(i));
                }
            }
        }  
        
        //labels empty candidate areas
        for(int i = 0; i < candidates.size(); i++){
            if(!candidates.get(i).startsWith("O") && !candidates.get(i).startsWith("T")){
                emptyRegions.add(candidates.get(i));
            }
        }
        
        //if no empty areas, find best area from other candidates
        //if player is already in an empty area, stay in that area        
        if(!emptyRegions.isEmpty()){
            for(int i = 0; i < emptyRegions.size(); i++){
                if(emptyRegions.get(i).equals(currentArea)){                    
                    //if near target, make decision on mext movement

                    if(parentCharacter.planner.isTargetReached(2f)){
                        int decision = this.runOrCall(bcInPos);
                        if(decision == 1){
                            Vector3f bestPos = this.getBestPositionInNonOccupied(currentArea, bcInPos);
                            parentCharacter.planner.setTargetPosition(bestPos);
                        }
                    }
//                    else{//if not near target, compare 
//                        System.out.println("dddd");
//                        Vector3f bestPos = this.getBestPositionInNonOccupied(currentArea, bcInPos);
//                        parentCharacter.planner.setTargetPosition(bestPos);
//                    }
                    stayStill = true;
                    break;
                }
            }
            
           //if player decides to move, move to the closest candidate area
           //designated by empty regions
            if(!stayStill){  
                Vector3f bestPos = this.getBestPositionInNonOccupied(this.getClosestAreaToPlayer(emptyRegions), bcInPos);               
                parentCharacter.planner.setTargetPosition(bestPos);
            }
        }
        //if player is in same area as possession player
        else if(currentArea.equals(possession)){
            Vector3f bestPos = this.getBestPositionInNonOccupied(currentArea, bcInPos);
            parentCharacter.planner.setTargetPosition(bestPos);
        }
        //candidate areas are all occupied by players
        else{
            this.getBestPositionInOccupied(candidates);        
        }
    }
    
    private void getBestPositionInOccupied(ArrayList<String> candidates){

    }
    
    private Vector3f getBestPositionInNonOccupied(String area, BasketballCharacter possessor){
        
        float distanceFromPossessor = parentCharacter.get2DPosition().distance(possessor.get2DPosition());
        float minDistFromPossessor = 7f;
        boolean isInArea = Court.getPlayerArea(parentCharacter).equals(area);
        boolean isWithinDist = distanceFromPossessor > minDistFromPossessor;
        
        
        if(isInArea && isWithinDist){
            return parentCharacter.get2DPosition();
        }
        else{
            Vector3f newPos = possessor.get2DPosition();
            while(!(possessor.get2DPosition().distance(newPos) > minDistFromPossessor)){
               newPos = Court.getRandomCoordinateInArea(area);
            }
            return newPos;
        }
    }
        
    private String getClosestAreaToPlayer(ArrayList<String> areas){
        float minDist = 1000000;
        String region = Court.getPlayerArea(parentCharacter);

        for(int i = 0; i < areas.size(); i++){
            float dist = parentCharacter.getPosition().distance(Court.getCentreCoordinate(areas.get(i)));
            if(dist < minDist){
                region = areas.get(i);
                minDist = dist;
            }            
        }
        return region;
    
    }
    
    private Vector3f getOpenPosition(BasketballCharacter bcInPos){
        
        float possessorPlayerAngle = Conversions.originToTargetAngle(bcInPos.getPosition(), parentCharacter.getPosition());
        float possessorFD = bcInPos.getFacingDirection();
        float playerFD = parentCharacter.getFacingDirection();
        
        
        ArrayList<Float> candidateAngles = new ArrayList<Float>();
        candidateAngles.add(possessorFD);
        candidateAngles.add(Conversions.adjustAngleTo360(possessorFD + 45));
        candidateAngles.add(Conversions.adjustAngleTo360(possessorFD - 45));
        
        float f = 10000;
        int ind = -1;
        
        for(int i = 0; i < candidateAngles.size(); i++){
            
            if(f > Conversions.minDistanceBetweenAngles(candidateAngles.get(i), possessorPlayerAngle)){
                f = candidateAngles.get(i);
                ind = i;
            }              
        }
        
        Vector3f vec = Conversions.degreesToNormalizedCoordinates(candidateAngles.get(ind)).mult(10);
        
        return bcInPos.getPosition().add(vec);
    }
    
    //options 
    //        - stay and face possessor
    //        - shuffle in area
    // return run = 1, call(stay) = 0
    private int runOrCall(BasketballCharacter bcInPos){
        
        if(this.openForPass(bcInPos)){
            return 0;
        }
        System.out.println("not open");
        return 1;
    }
    
    private boolean openForPass(BasketballCharacter bcInPos){
        float possessorPlayerAngle = Conversions.originToTargetAngle(bcInPos.getPosition(), parentCharacter.getPosition());
        ArrayList<BasketballCharacter> opp = parentCharacter.getOpponents();
   //     Conversions
        
       return CollisionMath.rayCollisionTest(bcInPos.getPosition(), Conversions.degreesToNormalizedCoordinates(possessorPlayerAngle), parentCharacter, opp, 3, 20);

        
   //     return true;
    }
    
    
}
